Conversation
…CP integration - Introduced new utility files: `assistantConstants.ts`, `mockMcp.ts`, and `responseProvider.ts` to support enhanced functionality in the assistant demo. - Updated `Assistant.vue` to utilize the new response provider and mock MCP tool, improving the interaction flow. - Revised documentation in `assistant.md` to reflect the inclusion of new demo files, ensuring comprehensive examples for users. - Updated sidebar items in theme configuration for better navigation and clarity on tool usage.
WalkthroughThe PR refactors the Assistant demo component to use a provider-based architecture with MCP (Model Context Protocol) tool integration, introduces comprehensive constants and configuration modules for UI data, and updates documentation headers for consistency. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Assistant as Assistant Component
participant Provider as Response Provider
participant API as /api/chat/completions
participant MockMCP as Mock MCP Stream
participant Tools as MCP Tools
User->>Assistant: Submit message with content
Assistant->>Provider: assistantResponseProvider(requestBody, abortSignal)
Provider->>Provider: Check for MCP trigger keywords
alt MCP Keywords Detected or Last Message is Tool
Provider->>MockMCP: mockMcpStream(requestBody, abortSignal)
MockMCP->>MockMCP: Extract search query from message
MockMCP->>Tools: Analyze for mcp_search tool call
Tools-->>MockMCP: tool_calls delta with extracted query
MockMCP-->>Provider: Yield tool_calls delta
MockMCP->>MockMCP: Generate assistant summary response
MockMCP-->>Provider: Yield assistant content with mock results
else Standard Chat Flow
Provider->>API: POST /api/chat/completions (streaming enabled)
API-->>Provider: SSE stream of chat completion
Provider->>Provider: Convert SSE to AsyncGenerator
end
Provider-->>Assistant: AsyncGenerator<ChatCompletion>
Assistant->>Assistant: Process deltas via toolPlugin
Assistant-->>User: Display response with formatted content
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📦 Package Previewpnpm add https://pkg.pr.new/opentiny/tiny-robot/@opentiny/tiny-robot@3a15fb0 pnpm add https://pkg.pr.new/opentiny/tiny-robot/@opentiny/tiny-robot-kit@3a15fb0 pnpm add https://pkg.pr.new/opentiny/tiny-robot/@opentiny/tiny-robot-svgs@3a15fb0 commit: 3a15fb0 |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/demos/examples/Assistant.vue (1)
193-214:⚠️ Potential issue | 🟠 MajorGuard JSON.parse in tool handler to prevent conversation failures on invalid tool arguments.
The
|| '{}'fallback only protects againstundefinedornull, not against malformed JSON strings. If the LLM generates invalid JSON intoolCall.function.arguments,JSON.parsewill throw an unhandled exception and break the conversation.Suggested fix
toolPlugin({ getTools: async () => MCP_TOOLS, callTool: async (toolCall) => { - const args = JSON.parse(toolCall.function?.arguments || '{}') - return callMcpTool(toolCall.function?.name || '', args) + let args: Record<string, unknown> = {} + try { + args = JSON.parse(toolCall.function?.arguments || '{}') + } catch { + // keep empty args on parse failure + } + return callMcpTool(toolCall.function?.name || '', args) }, }),
🤖 Fix all issues with AI agents
In `@docs/demos/examples/assistantConstants.ts`:
- Around line 265-268: getContainerStyles currently accesses
window.self/window.top which will crash during SSR; guard access by checking
typeof window !== "undefined" (and optionally typeof window.self !==
"undefined") before using window.self/window.top and return a safe default for
SSR. Update the getContainerStyles function to perform the typeof window check
first, then use the existing self/top logic when available; ensure the function
still returns the same objects ({ height: '100vh' } or { top: '112px', height:
'calc(100vh - 112px)' }) in the appropriate branches.
In `@docs/demos/examples/responseProvider.ts`:
- Around line 83-116: After the 300ms artificial delay and before emitting the
tool_calls yield, check the request abort signal and stop early if aborted:
after the await new Promise((r) => setTimeout(r, 300)) add a guard like if
(signal?.aborted) return (or throw new DOMException('Aborted', 'AbortError')),
so the code that constructs and yields the tool_calls object (which uses id,
query, extractSearchQuery, userContent) does not run when the request was
cancelled; also ensure any timers/listeners used by that Promise are cleaned up
if you wire the signal to clearTimeout.
| // --- Container styles --- | ||
| export function getContainerStyles(): Record<string, string> { | ||
| return window.self !== window.top ? { height: '100vh' } : { top: '112px', height: 'calc(100vh - 112px)' } | ||
| } |
There was a problem hiding this comment.
Guard window access to avoid SSR crashes.
If this runs during VitePress SSR, window is undefined and will throw. Add a guard so the docs build doesn’t break.
🔧 Proposed fix
export function getContainerStyles(): Record<string, string> {
- return window.self !== window.top ? { height: '100vh' } : { top: '112px', height: 'calc(100vh - 112px)' }
+ if (typeof window === 'undefined') {
+ return {}
+ }
+ return window.self !== window.top ? { height: '100vh' } : { top: '112px', height: 'calc(100vh - 112px)' }
}🤖 Prompt for AI Agents
In `@docs/demos/examples/assistantConstants.ts` around lines 265 - 268,
getContainerStyles currently accesses window.self/window.top which will crash
during SSR; guard access by checking typeof window !== "undefined" (and
optionally typeof window.self !== "undefined") before using
window.self/window.top and return a safe default for SSR. Update the
getContainerStyles function to perform the typeof window check first, then use
the existing self/top logic when available; ensure the function still returns
the same objects ({ height: '100vh' } or { top: '112px', height: 'calc(100vh -
112px)' }) in the appropriate branches.
| // First round: user message contains keyword -> return tool_calls | ||
| const userContent = typeof last?.content === 'string' ? last.content : '' | ||
| const query = extractSearchQuery(userContent) | ||
| await new Promise((r) => setTimeout(r, 300)) | ||
| yield { | ||
| id, | ||
| object: 'chat.completion.chunk', | ||
| created: Math.floor(Date.now() / 1000), | ||
| model: 'mock-mcp', | ||
| system_fingerprint: null, | ||
| choices: [ | ||
| { | ||
| index: 0, | ||
| message: undefined, | ||
| delta: { | ||
| role: 'assistant', | ||
| tool_calls: [ | ||
| { | ||
| index: 0, | ||
| id: 'call_mcp_search_' + Date.now(), | ||
| type: 'function', | ||
| function: { | ||
| name: 'mcp_search', | ||
| arguments: JSON.stringify({ query }), | ||
| }, | ||
| }, | ||
| ], | ||
| }, | ||
| finish_reason: 'tool_calls', | ||
| logprobs: null, | ||
| }, | ||
| ], | ||
| } | ||
| } |
There was a problem hiding this comment.
Respect abort before emitting tool_calls.
If the request is aborted during the 300ms delay, the tool call is still emitted. Add an abort check before yielding.
🛠️ Proposed fix
await new Promise((r) => setTimeout(r, 300))
+ if (abortSignal.aborted) return
yield {
id,
object: 'chat.completion.chunk',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // First round: user message contains keyword -> return tool_calls | |
| const userContent = typeof last?.content === 'string' ? last.content : '' | |
| const query = extractSearchQuery(userContent) | |
| await new Promise((r) => setTimeout(r, 300)) | |
| yield { | |
| id, | |
| object: 'chat.completion.chunk', | |
| created: Math.floor(Date.now() / 1000), | |
| model: 'mock-mcp', | |
| system_fingerprint: null, | |
| choices: [ | |
| { | |
| index: 0, | |
| message: undefined, | |
| delta: { | |
| role: 'assistant', | |
| tool_calls: [ | |
| { | |
| index: 0, | |
| id: 'call_mcp_search_' + Date.now(), | |
| type: 'function', | |
| function: { | |
| name: 'mcp_search', | |
| arguments: JSON.stringify({ query }), | |
| }, | |
| }, | |
| ], | |
| }, | |
| finish_reason: 'tool_calls', | |
| logprobs: null, | |
| }, | |
| ], | |
| } | |
| } | |
| // First round: user message contains keyword -> return tool_calls | |
| const userContent = typeof last?.content === 'string' ? last.content : '' | |
| const query = extractSearchQuery(userContent) | |
| await new Promise((r) => setTimeout(r, 300)) | |
| if (abortSignal.aborted) return | |
| yield { | |
| id, | |
| object: 'chat.completion.chunk', | |
| created: Math.floor(Date.now() / 1000), | |
| model: 'mock-mcp', | |
| system_fingerprint: null, | |
| choices: [ | |
| { | |
| index: 0, | |
| message: undefined, | |
| delta: { | |
| role: 'assistant', | |
| tool_calls: [ | |
| { | |
| index: 0, | |
| id: 'call_mcp_search_' + Date.now(), | |
| type: 'function', | |
| function: { | |
| name: 'mcp_search', | |
| arguments: JSON.stringify({ query }), | |
| }, | |
| }, | |
| ], | |
| }, | |
| finish_reason: 'tool_calls', | |
| logprobs: null, | |
| }, | |
| ], | |
| } | |
| } |
🤖 Prompt for AI Agents
In `@docs/demos/examples/responseProvider.ts` around lines 83 - 116, After the
300ms artificial delay and before emitting the tool_calls yield, check the
request abort signal and stop early if aborted: after the await new Promise((r)
=> setTimeout(r, 300)) add a guard like if (signal?.aborted) return (or throw
new DOMException('Aborted', 'AbortError')), so the code that constructs and
yields the tool_calls object (which uses id, query, extractSearchQuery,
userContent) does not run when the request was cancelled; also ensure any
timers/listeners used by that Promise are cleaned up if you wire the signal to
clearTimeout.

assistantConstants.ts,mockMcp.ts, andresponseProvider.tsto support enhanced functionality in the assistant demo.Assistant.vueto utilize the new response provider and mock MCP tool, improving the interaction flow.assistant.mdto reflect the inclusion of new demo files, ensuring comprehensive examples for users.Summary by CodeRabbit
Documentation
New Features
✏️ Tip: You can customize this high-level summary in your review settings.